package com.ds.rad.service;

import com.ds.annotation.MethodChinaName;
import com.ds.cluster.ServerNode;
import com.ds.common.JDSConstants;
import com.ds.common.JDSException;
import com.ds.common.logging.Log;
import com.ds.common.logging.LogFactory;
import com.ds.config.ErrorListResultModel;
import com.ds.config.ListResultModel;
import com.ds.esb.config.manager.ServiceBean;
import com.ds.esd.engine.*;
import com.ds.esd.engine.enums.PackageType;
import com.ds.esd.manager.plugins.api.enums.APIType;
import com.ds.esd.manager.plugins.api.node.APIComponentNode;
import com.ds.esd.manager.plugins.api.node.APIPaths;
import com.ds.esd.manager.plugins.api.node.XUIAPIConfig;
import com.ds.esd.tool.component.ModuleComponent;
import com.ds.server.JDSServer;
import com.ds.web.util.PageUtil;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.*;

@Controller
@RequestMapping(value = {"/RAD/api/"})
public class APIService {

    private static final Log logger = LogFactory.getLog(JDSConstants.CONFIG_KEY, APIService.class);

    @ResponseBody
    @RequestMapping(value = {"getPageServiceToolBox"}, method = {RequestMethod.POST, RequestMethod.GET})
    public ListResultModel<List<APIComponentNode>> getPageServiceToolBox(String pattern, String className, String projectName) {
        ListResultModel<List<APIComponentNode>> result = new ListResultModel<List<APIComponentNode>>();
        try {
            if (className != null && !className.equals("")) {
                Project project = this.getClient().getProjectByName(projectName);
                EUModule module = this.getClient().getModule(className, projectName);
                ModuleComponent moduleComponent = module.getComponent();
                List<APIComponentNode> extModuleList = new ArrayList<>();
                List<String> extCls = moduleComponent.getRequired();
                extModuleList.add(new APIComponentNode(moduleComponent, pattern));
                for (String extClsName : extCls) {
                    EUModule extModule = this.getClient().getModule(extClsName, projectName);
                    if (extModule != null) {
                        extModuleList.add(new APIComponentNode(extModule.getComponent(), pattern));
                    }
                }
                result.setData(extModuleList);
            }
        } catch (JDSException e) {
            result = new ErrorListResultModel<>();
            ((ErrorListResultModel) result).setErrcode(JDSException.APPLICATIONNOTFOUNDERROR);
            ((ErrorListResultModel) result).setErrdes(e.getMessage());
        }
        return result;
    }

    @ResponseBody
    @RequestMapping(value = {"getProjectServiceToolBox"}, method = {RequestMethod.POST, RequestMethod.GET})
    public ListResultModel<List<APIComponentNode>> getProjectServiceToolBox(String pattern, String projectName) {
        ListResultModel<List<APIComponentNode>> result = new ListResultModel<List<APIComponentNode>>();
        ProjectVersion projectVersion = null;
        try {
            projectVersion = this.getClient().getProjectVersionByName(projectName);
            APIComponentNode projectNode = new APIComponentNode(projectVersion, pattern, PackageType.userdef);
            List<APIComponentNode> sub = projectNode.getSub();
            Collections.sort(sub, new Comparator<APIComponentNode>() {
                public int compare(APIComponentNode o1, APIComponentNode o2) {
                    return o1.getPath().toLowerCase().compareTo(o1.getPath().toLowerCase());
                }
            });
            result.setData(sub);
        } catch (JDSException e) {
            result = new ErrorListResultModel<>();
            ((ErrorListResultModel) result).setErrcode(JDSException.APPLICATIONNOTFOUNDERROR);
            ((ErrorListResultModel) result).setErrdes(e.getMessage());
        }
        return result;
    }


    @ResponseBody
    @RequestMapping(value = {"getLocalServiceToolBox"}, method = {RequestMethod.POST, RequestMethod.GET})
    public ListResultModel<List<APIComponentNode>> getLocalServiceToolBox(String pattern, String currentClassName,String projectName) {
        ListResultModel<List<APIComponentNode>> result = new ListResultModel<List<APIComponentNode>>();
        Project project = null;
        try {
            project = this.getClient().getProjectByName(projectName);
            List<String> apis = null;//project.getApiFilter();
            List<APIComponentNode> configs = getLocalComponentService(pattern, apis);
            result.setData(configs);
        } catch (JDSException e) {
            result = new ErrorListResultModel<>();
            ((ErrorListResultModel) result).setErrcode(JDSException.APPLICATIONNOTFOUNDERROR);
            ((ErrorListResultModel) result).setErrdes(e.getMessage());
        }
        return result;
    }

    @MethodChinaName(cname = "获取配置")
    @RequestMapping(value = {"getAPIConfig"}, method = {RequestMethod.POST})
    public @ResponseBody
    ListResultModel<List<APIComponentNode>> getAPIConfig(String projectName, String id) {
        ListResultModel<List<APIComponentNode>> result = new ListResultModel<List<APIComponentNode>>();
        try {
            ESDClient client = ESDFacrory.getAdminESDClient();
            ProjectVersion service = client.getProjectVersionByName(projectName);
            List<String> ids = service.getProject().getConfig().getApiFilter();
            List<APIComponentNode> configs = new ArrayList<APIComponentNode>();
            List<APIComponentNode> componentNodes = getLocalComponentService(null, ids);
            for (APIComponentNode componentNode : componentNodes) {
                for (APIComponentNode sub : componentNode.getSub()) {
                    if (ids.contains(sub.getId())) {
                        configs.add(sub);
                    }
                }
            }
            result = PageUtil.getDefaultPageList(configs);
        } catch (JDSException e) {
            result = new ErrorListResultModel<>();
            ((ErrorListResultModel) result).setErrcode(JDSException.APPLICATIONNOTFOUNDERROR);
            ((ErrorListResultModel) result).setErrdes(e.getMessage());

        }
        return result;
    }


    public List<APIComponentNode> getLocalComponentService(String pattern, List<String> apiIds) throws JDSException {
        List<APIComponentNode> configs = new ArrayList<APIComponentNode>();
        long time = System.currentTimeMillis();

        List<APIPaths> paths = this.getClient().getAPITopPaths(pattern, APIType.userdef);
        for (APIPaths path : paths) {
            APIComponentNode topAPI = new APIComponentNode(path, true, pattern, apiIds);
            if (topAPI.getSub() != null && topAPI.getSub().size() > 0) {
                configs.add(topAPI);
            }
        }
        Arrays.sort(configs.toArray());
        return configs;
    }


    @ResponseBody
    @RequestMapping(value = {"getRemoteServiceByKey"}, method = {RequestMethod.POST, RequestMethod.GET})
    public ListResultModel<List<APIComponentNode>> getRemoteServiceService(String serverId, String pattern, String projectName) {
        ListResultModel<List<APIComponentNode>> result = new ListResultModel<List<APIComponentNode>>();
        ServerNode serverNode = JDSServer.getClusterClient().getServerNodeById(serverId);
        List<APIComponentNode> componentNodes = new ArrayList<APIComponentNode>();
        Set<? extends ServiceBean> beans = serverNode.getServices();
        Project project = null;
        try {
            project = this.getClient().getProjectByName(projectName);
            List<String> filters = project.getApiFilter();
            APIComponentNode serverAPI = new APIComponentNode(getClient().getAPIPaths(serverId + ":/"), true, pattern, filters);
            if (serverAPI != null && serverAPI.getSub() != null) {
                componentNodes.addAll(serverAPI.getSub());
            }
        } catch (JDSException e) {
            result = new ErrorListResultModel<>();
            ((ErrorListResultModel) result).setErrcode(JDSException.APPLICATIONNOTFOUNDERROR);
            ((ErrorListResultModel) result).setErrdes(e.getMessage());
        }
        Arrays.sort(componentNodes.toArray());
        result.setData(componentNodes);
        return result;

    }


    @ResponseBody
    @RequestMapping(value = {"getAPIService"}, method = {RequestMethod.POST, RequestMethod.GET})
    public ListResultModel<List<XUIAPIConfig>> getAPIService(String pattern,  String projectName) {
        ListResultModel<List<XUIAPIConfig>> result = new ListResultModel<List<XUIAPIConfig>>();
        List<XUIAPIConfig> services = new ArrayList<XUIAPIConfig>();
        try {
            services = this.getClient().searchLocalService(projectName, pattern);
            result.setData(services);
        } catch (JDSException e) {
            result = new ErrorListResultModel<>();
            ((ErrorListResultModel) result).setErrcode(JDSException.APPLICATIONNOTFOUNDERROR);
            ((ErrorListResultModel) result).setErrdes(e.getMessage());
        }


        return result;
    }


    @ResponseBody
    @RequestMapping(value = {"getAllServerToolBox"}, method = {RequestMethod.POST, RequestMethod.GET})
    public ListResultModel<List<APIComponentNode>> getRemoteServiceToolBox(String pattern, String projectName) {
        ListResultModel<List<APIComponentNode>> module = new ListResultModel<List<APIComponentNode>>();
        List<APIComponentNode> servers = new ArrayList<APIComponentNode>();
        List<ServerNode> serviceBeans = JDSServer.getClusterClient().getAllServer();
        for (ServerNode bean : serviceBeans) {
            if (bean.getServices().size() > 0) {
                APIComponentNode serverApiNode = new APIComponentNode(bean);
                servers.add(serverApiNode);
            }
        }
        module.setData(servers);
        return module;
    }


    public ESDClient getClient() throws JDSException {

        ESDClient client = ESDFacrory.getAdminESDClient();

        return client;
    }


}
